#include "infoboard.h"
#include "ghost.h"
#include "windowskin.h"
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QFontDatabase>
#include <QGraphicsDropShadowEffect>

using namespace Qt;
using namespace gs;

/*******************

ResistItem

********************/

ResistItem::ResistItem( GameBoardOrganizer * parent )
    :GameBoardItem( parent )
{
    this->setOpacity( 0 );
    _null = true;

    // split animations into two steps to make a good-looking chain
    _anim_0 = new QPropertyAnimation( this, "opacity" );
    _anim_0->setDuration( 100 );
    _anim_0->setEndValue( 0.5 );

    _anim_1 = new QPropertyAnimation( this, "opacity" );
    _anim_1->setDuration( 100 );
    _anim_1->setEndValue( 1 );

    _anim_group_0 = new QSequentialAnimationGroup( this );
    _anim_group_0->addAnimation( _anim_0 );
    _anim_group_0->addAnimation( _anim_1 );

    _anim_2 = new QPropertyAnimation( this, "scale" );
    _anim_2->setDuration( 300 );
    _anim_2->setStartValue( 2 );
    _anim_2->setEndValue( 1 );

    _anim_group_main = new QParallelAnimationGroup( this );
    _anim_group_main->addAnimation( _anim_2 );
    _anim_group_main->addAnimation( _anim_group_0 );

    connect( _anim_0, SIGNAL( finished() ), this, SIGNAL( half_finished() ) );
}
void ResistItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    if( !_null )
    {
        painter->drawPixmap( -_w/2, -_h/2, _w, _h, _qp );
    }
}

void ResistItem::setNull( bool null )
{
    _null = null;
    if( _null )
    {
        _anim_0->stop();
        _anim_1->stop();
        _anim_2->stop();
        _anim_group_0->stop();
        _anim_group_main->stop();
    }
}

void ResistItem::animate()
{
    if( !_null )
        _anim_group_main->start();
}

/*******************

ResistItemGroup

********************/

ResistItemGroup::ResistItemGroup(GameTable * table, GameBoardOrganizer * parent)
    : GameBoardOrganizer( table, parent )
{
    _resist0 = 0;
    _resist1 = 0;
    _resist2 = 0;
    _resist3 = 0;
    _resist4 = 0;

    _total_resist = _resist0 + _resist1 + _resist2 + _resist3 + _resist4;
    _qp0 = QPixmap( tr(":/resist/images/resist_0.png") );
    _qp1 = QPixmap( tr(":/resist/images/resist_1.png") );
    _qp2 = QPixmap( tr(":/resist/images/resist_2.png") );
    _qp3 = QPixmap( tr(":/resist/images/resist_3.png") );
    _qp4 = QPixmap( tr(":/resist/images/resist_4.png") );

    for( int i = 0; i < 10; i ++ )
    {
        _items << new ResistItem( this );
    }
    for( int i = 0; i < 9; i ++ )
    {
        /* set up the animation chain */
        connect( _items.at( i ), SIGNAL( half_finished() ),
                 _items.at( i + 1 ), SLOT( animate() ) );
    }
}

void ResistItemGroup::setGhost( Ghost* ghost )
{
    _resist0 = ghost->getResist0();
    _resist1 = ghost->getResist1();
    _resist2 = ghost->getResist2();
    _resist3 = ghost->getResist3();
    _resist4 = ghost->getResist4();
    _total_resist = _resist0 + _resist1 + _resist2 + _resist3 + _resist4;

    int i, count = 0;
    int hoffset = - _total_resist * ( _qp0.width() + _hgap ) / 2;
    int voffset = -_qp0.height() / 2;

    for( i = 0; i < _resist0; i ++ )
    {
        _items.at( count )->setResistance( _qp0 );
        _items.at( count )->setPos( hoffset, voffset );
        _items.at( count )->setOpacity( 0 );
        hoffset += _qp0.width() + _hgap;
        count ++;
    }
    for( i = 0; i < _resist1; i ++ )
    {
        _items.at( count )->setResistance( _qp1 );
        _items.at( count )->setPos( hoffset, voffset );
        _items.at( count )->setOpacity( 0 );
        hoffset += _qp0.width() + _hgap;
        count ++;
    }
    for( i = 0; i < _resist2; i ++ )
    {
        _items.at( count )->setResistance( _qp2 );
        _items.at( count )->setPos( hoffset, voffset );
        _items.at( count )->setOpacity( 0 );
        hoffset += _qp0.width() + _hgap;
        count ++;
    }
    for( i = 0; i < _resist3; i ++ )
    {
        _items.at( count )->setResistance( _qp3 );
        _items.at( count )->setPos( hoffset, voffset );
        _items.at( count )->setOpacity( 0 );
        hoffset += _qp0.width() + _hgap;
        count ++;
    }
    for( i = 0; i < _resist4; i ++ )
    {
        _items.at( count )->setResistance( _qp4 );
        _items.at( count )->setPos( hoffset, voffset );
        _items.at( count )->setOpacity( 0 );
        hoffset += _qp0.width() + _hgap;
        count ++;
    }

    for( ; count < _items.size(); count ++ )
    {
        _items.at( count )->setNull();
    }

    _items.at( 0 )->animate();
}

QRectF ResistItemGroup::boundingRect() const
{
    int w = 220;
    int h = 40;
    return QRectF( -w/2, -h/2, w, h );
}

void ResistItemGroup::updateState()
{
    update();
}


/*-----------------------------
    GhostSkillSlot
----------------------------*/
GhostSkillSlot::GhostSkillSlot(GameBoardOrganizer * parent)
    :GameBoardItem( parent ), _bg( QPixmap( ":/common/images/gcard_skill_slot.png" ) )
{
    this->setAcceptHoverEvents( true );
    _w = _bg.width();
    _h = _bg.height();
    _iconw = _w * 0.65;
    _iconh = _h * 0.65;
}

void GhostSkillSlot::setSkill( GhostSkills skill )
{
    _skill = skill;
    _qpskill = SkillQPixmap( skill );
    update();
}

QRectF GhostSkillSlot::boundingRect() const
{
    return QRectF( -_w / 2, -_h / 2, _w, _h );
}

void GhostSkillSlot::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    qreal myscale = 1;
    bool over = option->state & QStyle::State_MouseOver;
    if( over )
    {
        myscale = 0.98;
        painter->fillRect( -_iconw/2 , -_iconh/2,
                           _iconw, _iconh, white );
    }
    painter->drawPixmap( -_w/2 * myscale, -_h/2 * myscale, _w * myscale, _h * myscale, _bg );
    painter->drawPixmap( -_iconw/2 * myscale, -_iconh/2 * myscale,
                         _iconw * myscale, _iconh * myscale, _qpskill );

}

QPixmap GhostSkillSlot::SkillQPixmap( GhostSkills skill )
{
    switch( skill )
    {
    case INSTANT_HAUNT:
        return QPixmap( ":/common/images/skill_instant_haunt.png" );
    case ONE_MORE_CARD:
        return QPixmap( ":/common/images/skill_one_more_card.png" );
    case CURSE_DICE:
        return QPixmap( ":/common/images/skill_curse.png" );
    case SEAL_SKILLS:
        return QPixmap( ":/common/images/skill_seal_skill.png" );
    case TAO:
        return QPixmap( ":/common/images/skill_tao.png" );
    case LOSE_QI:
        return QPixmap( ":/common/images/skill_lose_qi.png" );
    case DICE_HOLDER:
        return QPixmap( ":/common/images/skill_dice_holder.png" );
    case YINYANG:
        return QPixmap( ":/common/images/skill_yinyang.png" );
    case HAUNTER:
        return QPixmap( ":/common/images/skill_haunt.png" );
    default:
        return QPixmap(":/common/images/default_skill.png" );
    }
}

/*-----------------------------
    GhostSkillSlotGroup
----------------------------*/

GhostSkillSlotGroup::GhostSkillSlotGroup(GameTable * table, GameBoardOrganizer * parent)
    : GameBoardOrganizer( table, parent )
{
    _skill_slot_l = new GhostSkillSlot( this );
    _skill_slot_m = new GhostSkillSlot( this );
    _skill_slot_r = new GhostSkillSlot( this );

    _w = _skill_slot_l->_w * 2 + HGAP * 2;
    _h = _skill_slot_l->_h;

    _skill_slot_l->setPos( - _skill_slot_l->_w / 2 - HGAP, - _skill_slot_l->_h / 2  );
    _skill_slot_m->setPos( 0, - _skill_slot_l->_h / 2  );
    _skill_slot_r->setPos( _skill_slot_l->_w / 2 + HGAP, - _skill_slot_l->_h / 2  );
}

QRectF GhostSkillSlotGroup::boundingRect() const
{
    return QRectF( -_w / 2, -_h / 2, _w, _h );
}

void GhostSkillSlotGroup::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
}

void GhostSkillSlotGroup::setGhost(Ghost *ghost)
{
    _ghost = ghost;
    _skill_slot_l->setSkill( ghost->getSkillL() );
    _skill_slot_m->setSkill( ghost->getSkillM() );
    _skill_slot_r->setSkill( ghost->getSkillR() );
    update();
}

/*-------------------------
  GhostCard
--------------------------*/
GhostCard::GhostCard( GameBoardOrganizer * parent )
    :GameBoardItem( parent )
{
    _qpbg   = QPixmap( ":/common/images/ghost_card_bg.png" );
    _qpcard = QPixmap( ":/common/images/unknown.png" );

    _color  = Qt::white;

    //_rib0   = QPixmap( ":/common/images/rib_r0.png" );
    //_rib1   = QPixmap( ":/common/images/rib_r1.png" );
    //_rib2   = QPixmap( ":/common/images/rib_r2.png" );
    //_rib3   = QPixmap( ":/common/images/rib_r3.png" );
    //_rib4   = QPixmap( ":/common/images/rib_r4.png" );
    //_qpboss = QPixmap( ":/common/images/boss_icon.png" );
    setAcceptHoverEvents( true );
}

QRectF GhostCard::boundingRect() const
{
    return QRectF(  -_qpcard.width() / 2, -_qpcard.height() / 2,  _qpcard.width(), _qpcard.height() );
}

void GhostCard::setGhost( Ghost *ghost )
{
    _ghost  = ghost;
    if( ghost->getID() == -1 )
    {
        _qpcard = QPixmap( ghost->getImagePath() );
    }
    else
    {
        _qpcard = QPixmap( ghost->getImagePath() );
    }
    _color  = Ghost::ColorToQColor( ghost->getColor() );
    update();
}

void GhostCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //bool over = option->state.testFlag( QStyle::State_MouseOver );
    painter->drawPixmap( -_qpcard.width() / 2, -_qpcard.height() / 2,_qpcard );
}


/*******************

InfoBoard

********************/

InfoBoard::InfoBoard(GameTable * table, GameBoardOrganizer * parent)
    : GameBoardOrganizer( table, parent )
{
    _bg         = QPixmap( ":/common/images/ginfo_bg.png" );
    INFO_WIDTH  = LeftTable::WIDTH;
    INFO_HEIGHT = LeftTable::HEIGHT;

    _dghost     = GhostManager::DefaultGhost();
    _ghost      = _dghost;
    _skillitem  = new GhostSkillSlotGroup( table, this );
    _carditem   = new GhostCard( this );
    _resistitem = new ResistItemGroup( table, this );

    QFontDatabase::addApplicationFont( tr(":/font/font/CHILLER.TTF") );
    _font = QFont( "Chiller" );
    _font.setPixelSize( 40 );
    _font.setBold( true );

    _skillitem->setPos( 0,  200 );
    _resistitem->setPos( 10, 125 );
    _carditem->setPos( 0,  - 35 );

    _carditem->setGhost(   _ghost );
    _resistitem->setGhost( _ghost );
    _skillitem->setGhost(  _ghost );

    /* Set up fade in/out animation for the card item */
    _anim_card0 = new QPropertyAnimation( _carditem, "opacity");
    _anim_card0->setDuration( 100 );
    _anim_card0->setEndValue( 0.0 );

    _anim_card1 = new QPropertyAnimation( _carditem, "opacity");
    _anim_card1->setDuration( 100 );
    _anim_card1->setEndValue( 1 );


    /* Card fade out animation */
    connect( this, SIGNAL( ghostChanged() ),
             _anim_card0, SLOT( start() ) );
    /* Card fade in animation */
    connect( _anim_card0, SIGNAL( finished() ),
             this, SLOT( fadeFinished() ) );

    this->setGhost( _ghost );
}

QRectF InfoBoard::boundingRect() const
{
    return QRectF( -INFO_WIDTH/2, -INFO_HEIGHT/2, INFO_WIDTH, INFO_HEIGHT );
}

Ghost* InfoBoard::currentGhost()
{
    return _ghost;
}

void InfoBoard::fadeFinished()
{
    _anim_card1->start();
    _carditem->setGhost( _ghost );
}

void InfoBoard::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setFont( _font );
    painter->fillRect(boundingRect(), Qt::black);
    painter->drawText( -2 - INFO_WIDTH/2, -INFO_HEIGHT/2 + 13, 220, 50, Qt::AlignCenter, _ghost->getName() );

    QPen pen;
    pen.setColor( white );

    painter->setPen( pen );
    painter->drawText( - INFO_WIDTH/2, -INFO_HEIGHT/2 + 15, 220, 50, Qt::AlignCenter, _ghost->getName() );

}

void InfoBoard::setGhost( Ghost *ghost )
{
    if( ghost == 0 )
    {
        _ghost = _dghost;
    }
    else
    {
        _ghost = ghost;
    }
    _skillitem->setGhost( _ghost );
    _resistitem->setGhost( _ghost );
    _resistitem->updateState();
    emit ghostChanged();
    update();
}

/* ---------------
   DeckBoard
---------------*/
DeckBoard::DeckBoard( GameTable * table, GameBoardOrganizer * parent )
    :InfoBoard( table, parent )
{
    _fliped = false;
    _info_board = 0;

    this->setAcceptHoverEvents( true );
    newDeck();
    connect( _carditem, SIGNAL( clicked() ),
             this, SLOT( clicked() ));
    connect( _carditem, SIGNAL( hover_entered() ),
             this, SLOT( hover_in() ));
    connect( _carditem, SIGNAL( hover_left() ),
             this, SLOT( hover_out() ));
}

void DeckBoard::clicked()
{
    if( !_fliped )
    {
        flip();
    }
    else
    {
        pop();
    }
}

void DeckBoard::hover_in()
{
    if( _info_board )
        _info_board->setGhost( this->currentGhost() );
}
void DeckBoard::hover_out()
{
    if( _info_board )
        _info_board->setGhost( 0 );
}

void DeckBoard::flip()
{
    this->setGhost( _deck.first() );
    _fliped = true;

    if( _ghost->isBoss() )
        emit bossInvoked();
}
Ghost* DeckBoard::pop()
{
    this->setGhost( _dghost );
    _fliped = false;
    if( _deck.size() == 1 )
        _carditem->setVisible( false );
    return _deck.takeFirst();
}
void DeckBoard::newDeck()
{
    GhostManager::CreateManager( this->getGameTable() );
    _deck << GhostManager::GetManager()->getList();
}
void DeckBoard::link_to_info( InfoBoard * board )
{
    _info_board = board;
}




